
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.*;
import org.jgap.*;
import org.jgap.gp.*;
import org.jgap.gp.function.*;
import org.jgap.gp.impl.*;
import org.jgap.gp.terminal.*;

//GP for choosing stocks problem
public class StockProblem
    extends GPProblem {

//variables for GP
  public static Variable vx1,vx2,vx3,vx4;
  public static Variable vx5,vx6,vx7,vx8,vx9,vx10,vx11,vx12,vx13,vx14,vx15,vx16,vx17,vx18,vx19,vx20,vx21,vx22,vx23,vx24,vx25,vx26,vx27,vx28,vx29,vx30,vx31,vx32,vx33,vx34,vx35,vx36,vx37,vx38,vx39,vx40,vx41,vx42,vx43,vx44,vx45,vx46,vx47,vx48,vx49,vx50,vx51,vx52,vx53,vx54,vx55,vx56,vx57,vx58,vx59,vx60,vx61,vx62,vx63,vx64,vx65,vx66,vx67,vx68,vx69,vx70,vx71,vx72,vx73,vx74,vx75,vx76,vx77,vx78,vx79,vx80,vx81,vx82,vx83,vx84,vx85,vx86,vx87,vx88,vx89,vx90,vx91,vx92,vx93,vx94,vx95,vx96,vx97,vx98,vx99,vx100,vx101,vx102,vx103,vx104,vx105,vx106,vx107,vx108,vx109,vx110,vx111,vx112,vx113,vx114,vx115,vx116,vx117,vx118,vx119,vx120,vx121,vx122,vx123,vx124,vx125,vx126,vx127,vx128,vx129,vx130,vx131,vx132,vx133,vx134,vx135,vx136,vx137,vx138,vx139,vx140,vx141,vx142,vx143,vx144,vx145,vx146,vx147,vx148,vx149,vx150,vx151,vx152,vx153,vx154,vx155,vx156,vx157,vx158,vx159,vx160,vx161,vx162,vx163,vx164,vx165,vx166,vx167,vx168,vx169,vx170,vx171,vx172,vx173,vx174,vx175,vx176,vx177,vx178,vx179,vx180,vx181,vx182,vx183,vx184,vx185,vx186,vx187,vx188,vx189,vx190,vx191,vx192,vx193,vx194,vx195,vx196,vx197,vx198,vx199,vx200,vx201,vx202,vx203,vx204;
  public static ArrayList<Variable> vars = new ArrayList<Variable>();

  public static ArrayList<Stock> stocks;
  public static int days;
  public static String modelfile;
  
  
  public StockProblem(GPConfiguration a_conf)
      throws InvalidConfigurationException {
    super(a_conf);
  }

  /**
   * This method is used for setting up the commands and terminals that can be
   * used to solve the problem.
   * @return GPGenotype
   * @throws InvalidConfigurationException
   */
  public GPGenotype create()
      throws InvalidConfigurationException {
	  
    GPConfiguration conf = getGPConfiguration();
    //we define the return type of the GP program.
    Class[] types = {
        // Return type of result-producing chromosome
        CommandGene.DoubleClass
        };
    
    //define the arguments of the GP parts.
    // -----------------------------------------------------------------------
    Class[][] argTypes = {
        // Arguments of result-producing chromosome: none
        {}
    };
    
    // define the set of available GP commands and terminals to use.

    CommandGene[][] nodeSets = { {
    	
    	//min closing price in last 200 days
    	vx1=Variable.create(conf, "X1", CommandGene.DoubleClass),
    	
    	//max closing price in last 20 days
    	vx2=Variable.create(conf, "X2", CommandGene.DoubleClass),
    	
    	//average of last 'days' days
    	vx3=Variable.create(conf, "X3", CommandGene.DoubleClass),
    	
    	//average of samples with skips of 'days'
    	vx4=Variable.create(conf, "X4", CommandGene.DoubleClass),
    	
    	//closing prices of last 200 days
    	vx5=Variable.create(conf, "X5", CommandGene.DoubleClass),
    	vx6=Variable.create(conf, "X6", CommandGene.DoubleClass),
    	vx7=Variable.create(conf, "X7", CommandGene.DoubleClass),
    	vx8=Variable.create(conf, "X8", CommandGene.DoubleClass),
    	vx9=Variable.create(conf, "X9", CommandGene.DoubleClass),
    	vx10=Variable.create(conf, "X10", CommandGene.DoubleClass),
    	vx11=Variable.create(conf, "X11", CommandGene.DoubleClass),
    	vx12=Variable.create(conf, "X12", CommandGene.DoubleClass),
    	vx13=Variable.create(conf, "X13", CommandGene.DoubleClass),
    	vx14=Variable.create(conf, "X14", CommandGene.DoubleClass),
    	vx15=Variable.create(conf, "X15", CommandGene.DoubleClass),
    	vx16=Variable.create(conf, "X16", CommandGene.DoubleClass),
    	vx17=Variable.create(conf, "X17", CommandGene.DoubleClass),
    	vx18=Variable.create(conf, "X18", CommandGene.DoubleClass),
    	vx19=Variable.create(conf, "X19", CommandGene.DoubleClass),
    	vx20=Variable.create(conf, "X20", CommandGene.DoubleClass),
    	vx21=Variable.create(conf, "X21", CommandGene.DoubleClass),
    	vx22=Variable.create(conf, "X22", CommandGene.DoubleClass),
    	vx23=Variable.create(conf, "X23", CommandGene.DoubleClass),
    	vx24=Variable.create(conf, "X24", CommandGene.DoubleClass),
    	vx25=Variable.create(conf, "X25", CommandGene.DoubleClass),
    	vx26=Variable.create(conf, "X26", CommandGene.DoubleClass),
    	vx27=Variable.create(conf, "X27", CommandGene.DoubleClass),
    	vx28=Variable.create(conf, "X28", CommandGene.DoubleClass),
    	vx29=Variable.create(conf, "X29", CommandGene.DoubleClass),
    	vx30=Variable.create(conf, "X30", CommandGene.DoubleClass),
    	vx31=Variable.create(conf, "X31", CommandGene.DoubleClass),
    	vx32=Variable.create(conf, "X32", CommandGene.DoubleClass),
    	vx33=Variable.create(conf, "X33", CommandGene.DoubleClass),
    	vx34=Variable.create(conf, "X34", CommandGene.DoubleClass),
    	vx35=Variable.create(conf, "X35", CommandGene.DoubleClass),
    	vx36=Variable.create(conf, "X36", CommandGene.DoubleClass),
    	vx37=Variable.create(conf, "X37", CommandGene.DoubleClass),
    	vx38=Variable.create(conf, "X38", CommandGene.DoubleClass),
    	vx39=Variable.create(conf, "X39", CommandGene.DoubleClass),
    	vx40=Variable.create(conf, "X40", CommandGene.DoubleClass),
    	vx41=Variable.create(conf, "X41", CommandGene.DoubleClass),
    	vx42=Variable.create(conf, "X42", CommandGene.DoubleClass),
    	vx43=Variable.create(conf, "X43", CommandGene.DoubleClass),
    	vx44=Variable.create(conf, "X44", CommandGene.DoubleClass),
    	vx45=Variable.create(conf, "X45", CommandGene.DoubleClass),
    	vx46=Variable.create(conf, "X46", CommandGene.DoubleClass),
    	vx47=Variable.create(conf, "X47", CommandGene.DoubleClass),
    	vx48=Variable.create(conf, "X48", CommandGene.DoubleClass),
    	vx49=Variable.create(conf, "X49", CommandGene.DoubleClass),
    	vx50=Variable.create(conf, "X50", CommandGene.DoubleClass),
    	vx51=Variable.create(conf, "X51", CommandGene.DoubleClass),
    	vx52=Variable.create(conf, "X52", CommandGene.DoubleClass),
    	vx53=Variable.create(conf, "X53", CommandGene.DoubleClass),
    	vx54=Variable.create(conf, "X54", CommandGene.DoubleClass),
    	vx55=Variable.create(conf, "X55", CommandGene.DoubleClass),
    	vx56=Variable.create(conf, "X56", CommandGene.DoubleClass),
    	vx57=Variable.create(conf, "X57", CommandGene.DoubleClass),
    	vx58=Variable.create(conf, "X58", CommandGene.DoubleClass),
    	vx59=Variable.create(conf, "X59", CommandGene.DoubleClass),
    	vx60=Variable.create(conf, "X60", CommandGene.DoubleClass),
    	vx61=Variable.create(conf, "X61", CommandGene.DoubleClass),
    	vx62=Variable.create(conf, "X62", CommandGene.DoubleClass),
    	vx63=Variable.create(conf, "X63", CommandGene.DoubleClass),
    	vx64=Variable.create(conf, "X64", CommandGene.DoubleClass),
    	vx65=Variable.create(conf, "X65", CommandGene.DoubleClass),
    	vx66=Variable.create(conf, "X66", CommandGene.DoubleClass),
    	vx67=Variable.create(conf, "X67", CommandGene.DoubleClass),
    	vx68=Variable.create(conf, "X68", CommandGene.DoubleClass),
    	vx69=Variable.create(conf, "X69", CommandGene.DoubleClass),
    	vx70=Variable.create(conf, "X70", CommandGene.DoubleClass),
    	vx71=Variable.create(conf, "X71", CommandGene.DoubleClass),
    	vx72=Variable.create(conf, "X72", CommandGene.DoubleClass),
    	vx73=Variable.create(conf, "X73", CommandGene.DoubleClass),
    	vx74=Variable.create(conf, "X74", CommandGene.DoubleClass),
    	vx75=Variable.create(conf, "X75", CommandGene.DoubleClass),
    	vx76=Variable.create(conf, "X76", CommandGene.DoubleClass),
    	vx77=Variable.create(conf, "X77", CommandGene.DoubleClass),
    	vx78=Variable.create(conf, "X78", CommandGene.DoubleClass),
    	vx79=Variable.create(conf, "X79", CommandGene.DoubleClass),
    	vx80=Variable.create(conf, "X80", CommandGene.DoubleClass),
    	vx81=Variable.create(conf, "X81", CommandGene.DoubleClass),
    	vx82=Variable.create(conf, "X82", CommandGene.DoubleClass),
    	vx83=Variable.create(conf, "X83", CommandGene.DoubleClass),
    	vx84=Variable.create(conf, "X84", CommandGene.DoubleClass),
    	vx85=Variable.create(conf, "X85", CommandGene.DoubleClass),
    	vx86=Variable.create(conf, "X86", CommandGene.DoubleClass),
    	vx87=Variable.create(conf, "X87", CommandGene.DoubleClass),
    	vx88=Variable.create(conf, "X88", CommandGene.DoubleClass),
    	vx89=Variable.create(conf, "X89", CommandGene.DoubleClass),
    	vx90=Variable.create(conf, "X90", CommandGene.DoubleClass),
    	vx91=Variable.create(conf, "X91", CommandGene.DoubleClass),
    	vx92=Variable.create(conf, "X92", CommandGene.DoubleClass),
    	vx93=Variable.create(conf, "X93", CommandGene.DoubleClass),
    	vx94=Variable.create(conf, "X94", CommandGene.DoubleClass),
    	vx95=Variable.create(conf, "X95", CommandGene.DoubleClass),
    	vx96=Variable.create(conf, "X96", CommandGene.DoubleClass),
    	vx97=Variable.create(conf, "X97", CommandGene.DoubleClass),
    	vx98=Variable.create(conf, "X98", CommandGene.DoubleClass),
    	vx99=Variable.create(conf, "X99", CommandGene.DoubleClass),
    	vx100=Variable.create(conf, "X100", CommandGene.DoubleClass),
    	vx101=Variable.create(conf, "X101", CommandGene.DoubleClass),
    	vx102=Variable.create(conf, "X102", CommandGene.DoubleClass),
    	vx103=Variable.create(conf, "X103", CommandGene.DoubleClass),
    	vx104=Variable.create(conf, "X104", CommandGene.DoubleClass),
    	vx105=Variable.create(conf, "X105", CommandGene.DoubleClass),
    	vx106=Variable.create(conf, "X106", CommandGene.DoubleClass),
    	vx107=Variable.create(conf, "X107", CommandGene.DoubleClass),
    	vx108=Variable.create(conf, "X108", CommandGene.DoubleClass),
    	vx109=Variable.create(conf, "X109", CommandGene.DoubleClass),
    	vx110=Variable.create(conf, "X110", CommandGene.DoubleClass),
    	vx111=Variable.create(conf, "X111", CommandGene.DoubleClass),
    	vx112=Variable.create(conf, "X112", CommandGene.DoubleClass),
    	vx113=Variable.create(conf, "X113", CommandGene.DoubleClass),
    	vx114=Variable.create(conf, "X114", CommandGene.DoubleClass),
    	vx115=Variable.create(conf, "X115", CommandGene.DoubleClass),
    	vx116=Variable.create(conf, "X116", CommandGene.DoubleClass),
    	vx117=Variable.create(conf, "X117", CommandGene.DoubleClass),
    	vx118=Variable.create(conf, "X118", CommandGene.DoubleClass),
    	vx119=Variable.create(conf, "X119", CommandGene.DoubleClass),
    	vx120=Variable.create(conf, "X120", CommandGene.DoubleClass),
    	vx121=Variable.create(conf, "X121", CommandGene.DoubleClass),
    	vx122=Variable.create(conf, "X122", CommandGene.DoubleClass),
    	vx123=Variable.create(conf, "X123", CommandGene.DoubleClass),
    	vx124=Variable.create(conf, "X124", CommandGene.DoubleClass),
    	vx125=Variable.create(conf, "X125", CommandGene.DoubleClass),
    	vx126=Variable.create(conf, "X126", CommandGene.DoubleClass),
    	vx127=Variable.create(conf, "X127", CommandGene.DoubleClass),
    	vx128=Variable.create(conf, "X128", CommandGene.DoubleClass),
    	vx129=Variable.create(conf, "X129", CommandGene.DoubleClass),
    	vx130=Variable.create(conf, "X130", CommandGene.DoubleClass),
    	vx131=Variable.create(conf, "X131", CommandGene.DoubleClass),
    	vx132=Variable.create(conf, "X132", CommandGene.DoubleClass),
    	vx133=Variable.create(conf, "X133", CommandGene.DoubleClass),
    	vx134=Variable.create(conf, "X134", CommandGene.DoubleClass),
    	vx135=Variable.create(conf, "X135", CommandGene.DoubleClass),
    	vx136=Variable.create(conf, "X136", CommandGene.DoubleClass),
    	vx137=Variable.create(conf, "X137", CommandGene.DoubleClass),
    	vx138=Variable.create(conf, "X138", CommandGene.DoubleClass),
    	vx139=Variable.create(conf, "X139", CommandGene.DoubleClass),
    	vx140=Variable.create(conf, "X140", CommandGene.DoubleClass),
    	vx141=Variable.create(conf, "X141", CommandGene.DoubleClass),
    	vx142=Variable.create(conf, "X142", CommandGene.DoubleClass),
    	vx143=Variable.create(conf, "X143", CommandGene.DoubleClass),
    	vx144=Variable.create(conf, "X144", CommandGene.DoubleClass),
    	vx145=Variable.create(conf, "X145", CommandGene.DoubleClass),
    	vx146=Variable.create(conf, "X146", CommandGene.DoubleClass),
    	vx147=Variable.create(conf, "X147", CommandGene.DoubleClass),
    	vx148=Variable.create(conf, "X148", CommandGene.DoubleClass),
    	vx149=Variable.create(conf, "X149", CommandGene.DoubleClass),
    	vx150=Variable.create(conf, "X150", CommandGene.DoubleClass),
    	vx151=Variable.create(conf, "X151", CommandGene.DoubleClass),
    	vx152=Variable.create(conf, "X152", CommandGene.DoubleClass),
    	vx153=Variable.create(conf, "X153", CommandGene.DoubleClass),
    	vx154=Variable.create(conf, "X154", CommandGene.DoubleClass),
    	vx155=Variable.create(conf, "X155", CommandGene.DoubleClass),
    	vx156=Variable.create(conf, "X156", CommandGene.DoubleClass),
    	vx157=Variable.create(conf, "X157", CommandGene.DoubleClass),
    	vx158=Variable.create(conf, "X158", CommandGene.DoubleClass),
    	vx159=Variable.create(conf, "X159", CommandGene.DoubleClass),
    	vx160=Variable.create(conf, "X160", CommandGene.DoubleClass),
    	vx161=Variable.create(conf, "X161", CommandGene.DoubleClass),
    	vx162=Variable.create(conf, "X162", CommandGene.DoubleClass),
    	vx163=Variable.create(conf, "X163", CommandGene.DoubleClass),
    	vx164=Variable.create(conf, "X164", CommandGene.DoubleClass),
    	vx165=Variable.create(conf, "X165", CommandGene.DoubleClass),
    	vx166=Variable.create(conf, "X166", CommandGene.DoubleClass),
    	vx167=Variable.create(conf, "X167", CommandGene.DoubleClass),
    	vx168=Variable.create(conf, "X168", CommandGene.DoubleClass),
    	vx169=Variable.create(conf, "X169", CommandGene.DoubleClass),
    	vx170=Variable.create(conf, "X170", CommandGene.DoubleClass),
    	vx171=Variable.create(conf, "X171", CommandGene.DoubleClass),
    	vx172=Variable.create(conf, "X172", CommandGene.DoubleClass),
    	vx173=Variable.create(conf, "X173", CommandGene.DoubleClass),
    	vx174=Variable.create(conf, "X174", CommandGene.DoubleClass),
    	vx175=Variable.create(conf, "X175", CommandGene.DoubleClass),
    	vx176=Variable.create(conf, "X176", CommandGene.DoubleClass),
    	vx177=Variable.create(conf, "X177", CommandGene.DoubleClass),
    	vx178=Variable.create(conf, "X178", CommandGene.DoubleClass),
    	vx179=Variable.create(conf, "X179", CommandGene.DoubleClass),
    	vx180=Variable.create(conf, "X180", CommandGene.DoubleClass),
    	vx181=Variable.create(conf, "X181", CommandGene.DoubleClass),
    	vx182=Variable.create(conf, "X182", CommandGene.DoubleClass),
    	vx183=Variable.create(conf, "X183", CommandGene.DoubleClass),
    	vx184=Variable.create(conf, "X184", CommandGene.DoubleClass),
    	vx185=Variable.create(conf, "X185", CommandGene.DoubleClass),
    	vx186=Variable.create(conf, "X186", CommandGene.DoubleClass),
    	vx187=Variable.create(conf, "X187", CommandGene.DoubleClass),
    	vx188=Variable.create(conf, "X188", CommandGene.DoubleClass),
    	vx189=Variable.create(conf, "X189", CommandGene.DoubleClass),
    	vx190=Variable.create(conf, "X190", CommandGene.DoubleClass),
    	vx191=Variable.create(conf, "X191", CommandGene.DoubleClass),
    	vx192=Variable.create(conf, "X192", CommandGene.DoubleClass),
    	vx193=Variable.create(conf, "X193", CommandGene.DoubleClass),
    	
    	vx194=Variable.create(conf, "X194", CommandGene.DoubleClass),
    	vx195=Variable.create(conf, "X195", CommandGene.DoubleClass),
    	vx196=Variable.create(conf, "X196", CommandGene.DoubleClass),
    	vx197=Variable.create(conf, "X197", CommandGene.DoubleClass),
    	vx198=Variable.create(conf, "X198", CommandGene.DoubleClass),
    	vx199=Variable.create(conf, "X199", CommandGene.DoubleClass),
    	vx200=Variable.create(conf, "X200", CommandGene.DoubleClass),
    	vx201=Variable.create(conf, "X201", CommandGene.DoubleClass),
    	vx202=Variable.create(conf, "X202", CommandGene.DoubleClass),
    	vx203=Variable.create(conf, "X203", CommandGene.DoubleClass),
    	vx204=Variable.create(conf, "X204", CommandGene.DoubleClass),

    	//the used operators
    	new Multiply(conf, CommandGene.DoubleClass),
    	new Multiply3(conf, CommandGene.DoubleClass),
        new Divide(conf, CommandGene.DoubleClass),
        new Sine(conf, CommandGene.DoubleClass),
        new Exp(conf, CommandGene.DoubleClass),
        new Subtract(conf, CommandGene.DoubleClass),
        new Pow(conf, CommandGene.DoubleClass),
        new Add(conf, CommandGene.DoubleClass),
   
        new Terminal(conf, CommandGene.DoubleClass, 2.0d, 10.0d, true)}
    };
 
    return GPGenotype.randomInitialGenotype(conf, types, argTypes, nodeSets,
        300, true);
  }

  /**
   * run the GP
   */
  public static void run_alg(ArrayList<Stock> stocks_arr,int numDays,String model)
      throws Exception {

	  //updating input paramters
	  modelfile=model;
	  stocks=stocks_arr;
	  days=numDays;

	  //Setup algorithm's parameters.

	  GPConfiguration config = new GPConfiguration();

	  //delta fitness because we compute error rate and want to minimize fitness
	  config.setGPFitnessEvaluator(new DeltaGPFitnessEvaluator());
	  config.setMaxInitDepth(4);
	  config.setPopulationSize(1000);
	  config.setMaxCrossoverDepth(8);
	  config.setFitnessFunction(new StockProblem.FormulaFitnessFunction());
	  config.setStrictProgramCreation(true);

	  GPProblem problem = new StockProblem(config);
	  // create the genotype of the problem, define the GP commands and terminals that can be used
	  GPGenotype gp = problem.create();
	  gp.setVerboseOutput(false);
	  
	  //run for 200 generations
	  gp.evolve(200);

	  //gp.outputSolution(gp.getAllTimeBest());
	  //System.out.println(gp.getAllTimeBest().toStringNorm(0));

	  //write best solution found to given model file
	  FileOutputStream fw=new FileOutputStream(modelfile);
	  ObjectOutputStream os=new ObjectOutputStream(fw);
	  os.writeObject(new IGPProgramHolder(gp.getAllTimeBest(),vx1,vx2,vx3,vx4,vx5,vx6,vx7,vx8,vx9,vx10,vx11,vx12,vx13,vx14,vx15,vx16,vx17,vx18,vx19,vx20,vx21,vx22,vx23,vx24,vx25,vx26,vx27,vx28,vx29,vx30,vx31,vx32,vx33,vx34,vx35,vx36,vx37,vx38,vx39,vx40,vx41,vx42,vx43,vx44,vx45,vx46,vx47,vx48,vx49,vx50,vx51,vx52,vx53,vx54,vx55,vx56,vx57,vx58,vx59,vx60,vx61,vx62,vx63,vx64,vx65,vx66,vx67,vx68,vx69,vx70,vx71,vx72,vx73,vx74,vx75,vx76,vx77,vx78,vx79,vx80,vx81,vx82,vx83,vx84,vx85,vx86,vx87,vx88,vx89,vx90,vx91,vx92,vx93,vx94,vx95,vx96,vx97,vx98,vx99,vx100,vx101,vx102,vx103,vx104,vx105,vx106,vx107,vx108,vx109,vx110,vx111,vx112,vx113,vx114,vx115,vx116,vx117,vx118,vx119,vx120,vx121,vx122,vx123,vx124,vx125,vx126,vx127,vx128,vx129,vx130,vx131,vx132,vx133,vx134,vx135,vx136,vx137,vx138,vx139,vx140,vx141,vx142,vx143,vx144,vx145,vx146,vx147,vx148,vx149,vx150,vx151,vx152,vx153,vx154,vx155,vx156,vx157,vx158,vx159,vx160,vx161,vx162,vx163,vx164,vx165,vx166,vx167,vx168,vx169,vx170,vx171,vx172,vx173,vx174,vx175,vx176,vx177,vx178,vx179,vx180,vx181,vx182,vx183,vx184,vx185,vx186,vx187,vx188,vx189,vx190,vx191,vx192,vx193,vx194,vx195,vx196,vx197,vx198,vx199,vx200,vx201,vx202,vx203,vx204));//vx194,vx195,vx196,vx197,vx198,vx199,vx200,vx201,vx202,vx203,vx204));
	  os.close();



  }


  //function that returns minimum and maximum value in the given array from start index to start+200
  public static double[] getMinAndMax(ArrayList<Double> prices,int start)
  {
	  double min=20000;
	  double max=-1;

	  for(int i=start;i<start+200;i++)
	  {
		  //found new max
		  if(prices.get(i)>max)
		  {
			  max=prices.get(i);
		  }
		  //found new min
		  if(prices.get(i)<min)
		  {
			  min=prices.get(i);
		  }
	  }

	  return new double[]{min,max};
  }
  
  //computes avg of last 'days' days (from start index to start+200)
  public static double avg(int start, int days,ArrayList<Double> prices) {

	  double sum=0;
	  for(int i=start+200-days;i<200+start;i++)
		  sum+=prices.get(i);
	  return sum/days;
  }
  
  //comopute average of 200/days samples with jumps of days
  public static double movAvg(int start, int days,ArrayList<Double> prices) {
	
	  double sum=0;
	  int count=0;
	  for(int i=start;i<200+start;i+=days)
	  {
		  sum+=prices.get(i);
		  count++;
	  }
	  return sum/count;
  }
  
  /**
   * Fitness function for evaluating the produced formulas, represented as GPprograms
   */
  public static class FormulaFitnessFunction extends GPFitnessFunction {

	private static final long serialVersionUID = 1L;


	protected double evaluate(final IGPProgram a_subject) {
      return computeRawFitness(a_subject);
    }

	//evaluate fitness by dividing the history to intervals of 200 days and summing the difference
	//between current GPprogram result to real result (summing to all stocks)
    public double computeRawFitness(final IGPProgram ind) {
    	
    	double sum=0;
    	for(Stock s:stocks){
    		Object[] noargs = new Object[0];
    		ArrayList<Double> prices=s.getPrices();
    		
    		//intervals of 200 days
    		for(int i=0;i<=300-days-1;i+=100){
    		
    			double[] minmax=getMinAndMax(s.getPrices(), i);
    			
    			//min of 200 days
    			vx1.set(minmax[0]);
    			
    			//max of 200 days
    			vx2.set(minmax[1]);
    			
    			//avg
    			vx3.set(avg(i,days,s.getPrices()));
    			
    			//moving avg
    			vx4.set(movAvg(i,days,s.getPrices()));
    			
    			//values of closing prices in all 200 days
    			vx5.set(s.getPrices().get(i));
        		vx6.set(s.getPrices().get(i+1));
        		vx7.set(s.getPrices().get(i+2));
        		vx8.set(s.getPrices().get(i+3));
        		vx9.set(s.getPrices().get(i+4));
        		vx10.set(s.getPrices().get(i+5));
        		vx11.set(s.getPrices().get(i+6));
        		vx12.set(s.getPrices().get(i+7));
        		vx13.set(s.getPrices().get(i+8));
        		vx14.set(s.getPrices().get(i+9));
        		vx15.set(s.getPrices().get(i+10));
        		vx16.set(s.getPrices().get(i+11));
        		vx17.set(s.getPrices().get(i+12));
        		vx18.set(s.getPrices().get(i+13));
        		vx19.set(s.getPrices().get(i+14));
        		vx20.set(s.getPrices().get(i+15));
        		vx21.set(s.getPrices().get(i+16));
        		vx22.set(s.getPrices().get(i+17));
        		vx23.set(s.getPrices().get(i+18));
        		vx24.set(s.getPrices().get(i+19));
        		vx25.set(s.getPrices().get(i+20));
        		vx26.set(s.getPrices().get(i+21));
        		vx27.set(s.getPrices().get(i+22));
        		vx28.set(s.getPrices().get(i+23));
        		vx29.set(s.getPrices().get(i+24));
        		vx30.set(s.getPrices().get(i+25));
        		vx31.set(s.getPrices().get(i+26));
        		vx32.set(s.getPrices().get(i+27));
        		vx33.set(s.getPrices().get(i+28));
        		vx34.set(s.getPrices().get(i+29));
        		vx35.set(s.getPrices().get(i+30));
        		vx36.set(s.getPrices().get(i+31));
        		vx37.set(s.getPrices().get(i+32));
        		vx38.set(s.getPrices().get(i+33));
        		vx39.set(s.getPrices().get(i+34));
        		vx40.set(s.getPrices().get(i+35));
        		vx41.set(s.getPrices().get(i+36));
        		vx42.set(s.getPrices().get(i+37));
        		vx43.set(s.getPrices().get(i+38));
        		vx44.set(s.getPrices().get(i+39));
        		vx45.set(s.getPrices().get(i+40));
        		vx46.set(s.getPrices().get(i+41));
        		vx47.set(s.getPrices().get(i+42));
        		vx48.set(s.getPrices().get(i+43));
        		vx49.set(s.getPrices().get(i+44));
        		vx50.set(s.getPrices().get(i+45));
        		vx51.set(s.getPrices().get(i+46));
        		vx52.set(s.getPrices().get(i+47));
        		vx53.set(s.getPrices().get(i+48));
        		vx54.set(s.getPrices().get(i+49));
        		vx55.set(s.getPrices().get(i+50));
        		vx56.set(s.getPrices().get(i+51));
        		vx57.set(s.getPrices().get(i+52));
        		vx58.set(s.getPrices().get(i+53));
        		vx59.set(s.getPrices().get(i+54));
        		vx60.set(s.getPrices().get(i+55));
        		vx61.set(s.getPrices().get(i+56));
        		vx62.set(s.getPrices().get(i+57));
        		vx63.set(s.getPrices().get(i+58));
        		vx64.set(s.getPrices().get(i+59));
        		vx65.set(s.getPrices().get(i+60));
        		vx66.set(s.getPrices().get(i+61));
        		vx67.set(s.getPrices().get(i+62));
        		vx68.set(s.getPrices().get(i+63));
        		vx69.set(s.getPrices().get(i+64));
        		vx70.set(s.getPrices().get(i+65));
        		vx71.set(s.getPrices().get(i+66));
        		vx72.set(s.getPrices().get(i+67));
        		vx73.set(s.getPrices().get(i+68));
        		vx74.set(s.getPrices().get(i+69));
        		vx75.set(s.getPrices().get(i+70));
        		vx76.set(s.getPrices().get(i+71));
        		vx77.set(s.getPrices().get(i+72));
        		vx78.set(s.getPrices().get(i+73));
        		vx79.set(s.getPrices().get(i+74));
        		vx80.set(s.getPrices().get(i+75));
        		vx81.set(s.getPrices().get(i+76));
        		vx82.set(s.getPrices().get(i+77));
        		vx83.set(s.getPrices().get(i+78));
        		vx84.set(s.getPrices().get(i+79));
        		vx85.set(s.getPrices().get(i+80));
        		vx86.set(s.getPrices().get(i+81));
        		vx87.set(s.getPrices().get(i+82));
        		vx88.set(s.getPrices().get(i+83));
        		vx89.set(s.getPrices().get(i+84));
        		vx90.set(s.getPrices().get(i+85));
        		vx91.set(s.getPrices().get(i+86));
        		vx92.set(s.getPrices().get(i+87));
        		vx93.set(s.getPrices().get(i+88));
        		vx94.set(s.getPrices().get(i+89));
        		vx95.set(s.getPrices().get(i+90));
        		vx96.set(s.getPrices().get(i+91));
        		vx97.set(s.getPrices().get(i+92));
        		vx98.set(s.getPrices().get(i+93));
        		vx99.set(s.getPrices().get(i+94));
        		vx100.set(s.getPrices().get(i+95));
        		vx101.set(s.getPrices().get(i+96));
        		vx102.set(s.getPrices().get(i+97));
        		vx103.set(s.getPrices().get(i+98));
        		vx104.set(s.getPrices().get(i+99));
        		vx105.set(s.getPrices().get(i+100));
        		vx106.set(s.getPrices().get(i+101));
        		vx107.set(s.getPrices().get(i+102));
        		vx108.set(s.getPrices().get(i+103));
        		vx109.set(s.getPrices().get(i+104));
        		vx110.set(s.getPrices().get(i+105));
        		vx111.set(s.getPrices().get(i+106));
        		vx112.set(s.getPrices().get(i+107));
        		vx113.set(s.getPrices().get(i+108));
        		vx114.set(s.getPrices().get(i+109));
        		vx115.set(s.getPrices().get(i+110));
        		vx116.set(s.getPrices().get(i+111));
        		vx117.set(s.getPrices().get(i+112));
        		vx118.set(s.getPrices().get(i+113));
        		vx119.set(s.getPrices().get(i+114));
        		vx120.set(s.getPrices().get(i+115));
        		vx121.set(s.getPrices().get(i+116));
        		vx122.set(s.getPrices().get(i+117));
        		vx123.set(s.getPrices().get(i+118));
        		vx124.set(s.getPrices().get(i+119));
        		vx125.set(s.getPrices().get(i+120));
        		vx126.set(s.getPrices().get(i+121));
        		vx127.set(s.getPrices().get(i+122));
        		vx128.set(s.getPrices().get(i+123));
        		vx129.set(s.getPrices().get(i+124));
        		vx130.set(s.getPrices().get(i+125));
        		vx131.set(s.getPrices().get(i+126));
        		vx132.set(s.getPrices().get(i+127));
        		vx133.set(s.getPrices().get(i+128));
        		vx134.set(s.getPrices().get(i+129));
        		vx135.set(s.getPrices().get(i+130));
        		vx136.set(s.getPrices().get(i+131));
        		vx137.set(s.getPrices().get(i+132));
        		vx138.set(s.getPrices().get(i+133));
        		vx139.set(s.getPrices().get(i+134));
        		vx140.set(s.getPrices().get(i+135));
        		vx141.set(s.getPrices().get(i+136));
        		vx142.set(s.getPrices().get(i+137));
        		vx143.set(s.getPrices().get(i+138));
        		vx144.set(s.getPrices().get(i+139));
        		vx145.set(s.getPrices().get(i+140));
        		vx146.set(s.getPrices().get(i+141));
        		vx147.set(s.getPrices().get(i+142));
        		vx148.set(s.getPrices().get(i+143));
        		vx149.set(s.getPrices().get(i+144));
        		vx150.set(s.getPrices().get(i+145));
        		vx151.set(s.getPrices().get(i+146));
        		vx152.set(s.getPrices().get(i+147));
        		vx153.set(s.getPrices().get(i+148));
        		vx154.set(s.getPrices().get(i+149));
        		vx155.set(s.getPrices().get(i+150));
        		vx156.set(s.getPrices().get(i+151));
        		vx157.set(s.getPrices().get(i+152));
        		vx158.set(s.getPrices().get(i+153));
        		vx159.set(s.getPrices().get(i+154));
        		vx160.set(s.getPrices().get(i+155));
        		vx161.set(s.getPrices().get(i+156));
        		vx162.set(s.getPrices().get(i+157));
        		vx163.set(s.getPrices().get(i+158));
        		vx164.set(s.getPrices().get(i+159));
        		vx165.set(s.getPrices().get(i+160));
        		vx166.set(s.getPrices().get(i+161));
        		vx167.set(s.getPrices().get(i+162));
        		vx168.set(s.getPrices().get(i+163));
        		vx169.set(s.getPrices().get(i+164));
        		vx170.set(s.getPrices().get(i+165));
        		vx171.set(s.getPrices().get(i+166));
        		vx172.set(s.getPrices().get(i+167));
        		vx173.set(s.getPrices().get(i+168));
        		vx174.set(s.getPrices().get(i+169));
        		vx175.set(s.getPrices().get(i+170));
        		vx176.set(s.getPrices().get(i+171));
        		vx177.set(s.getPrices().get(i+172));
        		vx178.set(s.getPrices().get(i+173));
        		vx179.set(s.getPrices().get(i+174));
        		vx180.set(s.getPrices().get(i+175));
        		vx181.set(s.getPrices().get(i+176));
        		vx182.set(s.getPrices().get(i+177));
        		vx183.set(s.getPrices().get(i+178));
        		vx184.set(s.getPrices().get(i+179));
        		vx185.set(s.getPrices().get(i+180));
        		vx186.set(s.getPrices().get(i+181));
        		vx187.set(s.getPrices().get(i+182));
        		vx188.set(s.getPrices().get(i+183));
        		vx189.set(s.getPrices().get(i+184));
        		vx190.set(s.getPrices().get(i+185));
        		vx191.set(s.getPrices().get(i+186));
        		vx192.set(s.getPrices().get(i+187));
        		vx193.set(s.getPrices().get(i+188));
        		vx194.set(s.getPrices().get(i+189));
        		vx195.set(s.getPrices().get(i+190));
        		vx196.set(s.getPrices().get(i+191));
        		vx197.set(s.getPrices().get(i+192));
        		vx198.set(s.getPrices().get(i+193));
        		vx199.set(s.getPrices().get(i+194));
        		vx200.set(s.getPrices().get(i+195));
        		vx201.set(s.getPrices().get(i+196));
        		vx202.set(s.getPrices().get(i+197));
        		vx203.set(s.getPrices().get(i+198));
        		vx204.set(s.getPrices().get(i+199));
        		
        		//executing the gpprogram on the given variables
        		double result = ind.execute_double(0, noargs);
        		
        		//if the result is NAN or infinity, the formula isn't good
        		if(Double.isNaN(result) || Double.isInfinite(result))
        			return 20000;

        		//summing the difference
        		sum+=Math.abs(result-prices.get(i+200+days));
    		}
    	}
    	return sum;
     
     
    }


  }
}